package com.springboot.util;

import java.io.*;

import org.springframework.util.StringUtils;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
import com.springboot.entity.Item;
import com.springboot.entity.Pipe;
import com.springboot.entity.Project;

/**
 * 导出指定格式PDF文档工具类
 */
public class AppExport extends PdfPageEventHelper {

    public ByteArrayOutputStream initFile(Project project) {
        try {
            Rectangle rectangle = new Rectangle(842, 595);
            Document document = new Document(rectangle);
            document.setMargins(50, 50, 50, 40);

            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            PdfWriter writer = PdfWriter.getInstance(document, stream);
            writer.setPageEvent(this);
            document.open(); // 打开文档

            Font font = getFont(6);
            BaseColor color = new BaseColor(205, 205, 205);
            for (Pipe pipe : project.getPipes()) {
                // 新建页面
                document.newPage();

                int[] width1 = new int[]{145, 15, 105, 15, 75, 15, 145, 15, 30, 15, 45, 15, 105};
                PdfPTable table1 = getTable(width1);
                assert table1 != null;
                // 添加页面标题
                writeTitle(table1, 1, 13, 12, font, "MSDI LTD. South");
                // 添加title
                writeTitle(table1, 1, 1, 8, font, "Surveyed by (Operator)");
                writeTitle(table1, 1, 1, 0, font, "");
                writeTitle(table1, 1, 1, 0, font, "Contract No.");
                writeTitle(table1, 1, 1, 0, font, "");
                writeTitle(table1, 1, 1, 0, font, "Job No.");
                writeTitle(table1, 1, 1, 0, font, "");
                writeTitle(table1, 1, 1, 0, font, "Drainage Area Code");
                writeTitle(table1, 1, 1, 0, font, "");
                writeTitle(table1, 1, 1, 0, font, "Div");
                writeTitle(table1, 1, 1, 0, font, "");
                writeTitle(table1, 1, 1, 0, font, "District");
                writeTitle(table1, 1, 1, 0, font, "");
                writeTitle(table1, 1, 1, 0, font, "Pipe Length Reference");
                // 添加title
                writeValue(table1, 1, 1, 12, font, pipe.getOperator());
                writeTitle(table1, 1, 1, 0, font, "");
                writeValue(table1, 1, 1, 0, font, "");
                writeTitle(table1, 1, 1, 0, font, "");
                writeValue(table1, 1, 1, 0, font, pipe.getWorkorder());
                writeTitle(table1, 1, 1, 0, font, "");
                writeValue(table1, 1, 1, 0, font, pipe.getAreacode());
                writeTitle(table1, 1, 1, 0, font, "");
                writeValue(table1, 1, 1, 0, font, pipe.getDivision());
                writeTitle(table1, 1, 1, 0, font, "");
                writeValue(table1, 1, 1, 0, font, pipe.getDistrict1());
                writeTitle(table1, 1, 1, 0, font, "");
                writeValue(table1, 1, 1, 0, font, pipe.getReference());
                tableWrap(table1, 4);
                document.add(table1);

                int[] width2 = new int[]{65, 15, 65, 15, 285, 15, 280};
                PdfPTable table2 = getTable(width2);
                assert table2 != null;
                // 添加title
                writeTitle(table2, 1, 1, 8, font, "Date");
                writeTitle(table2, 1, 1, 0, font, "");
                writeTitle(table2, 1, 1, 0, font, "Time");
                writeTitle(table2, 1, 1, 0, font, "");
                writeTitle(table2, 1, 1, 0, font, "Road Name");
                writeTitle(table2, 1, 1, 0, font, "");
                writeTitle(table2, 1, 1, 0, font, "Place");
                // 添加value
                writeValue(table2, 1, 1, 12, font, pipe.getDate());
                writeTitle(table2, 1, 1, 0, font, "");
                writeValue(table2, 1, 1, 0, font, pipe.getTime());
                writeTitle(table2, 1, 1, 0, font, "");
                writeValue(table2, 1, 1, 0, font, pipe.getRoadname());
                writeTitle(table2, 1, 1, 0, font, "");
                writeValue(table2, 1, 1, 0, font, pipe.getDistrict2() + "," + pipe.getDistrict3());
                tableWrap(table2, 4);
                document.add(table2);

                int[] width3 = new int[]{145, 15, 60, 15, 60, 15, 60, 15, 130, 15, 60, 15, 60, 15, 60};
                PdfPTable table3 = getTable(width3);
                assert table3 != null;
                // 添加title
                writeTitle(table3, 1, 1, 8, font, "Start Manhole No");
                writeTitle(table3, 1, 1, 0, font, "");
                writeTitle(table3, 1, 1, 0, font, "Depth");
                writeTitle(table3, 1, 1, 0, font, "");
                writeTitle(table3, 1, 1, 0, font, "Cover Level");
                writeTitle(table3, 1, 1, 0, font, "");
                writeTitle(table3, 1, 1, 0, font, "Invert Level");
                writeTitle(table3, 1, 1, 0, font, "");
                writeTitle(table3, 1, 1, 8, font, "Finish Manhole No");
                writeTitle(table3, 1, 1, 0, font, "");
                writeTitle(table3, 1, 1, 0, font, "Depth");
                writeTitle(table3, 1, 1, 0, font, "");
                writeTitle(table3, 1, 1, 0, font, "Cover Level");
                writeTitle(table3, 1, 1, 0, font, "");
                writeTitle(table3, 1, 1, 0, font, "Invert Level");
                // 添加value
                writeValue(table3, 1, 1, 12, font, pipe.getSmanholeno());
                writeTitle(table3, 1, 1, 0, font, "");
                writeValue(table3, 1, 1, 0, font, pipe.getSdepth());
                writeTitle(table3, 1, 1, 0, font, "");
                writeValue(table3, 1, 1, 0, font, pipe.getScoverlevel());
                writeTitle(table3, 1, 1, 0, font, "");
                writeValue(table3, 1, 1, 0, font, pipe.getSinvertlevel());
                writeTitle(table3, 1, 1, 8, font, "");
                writeValue(table3, 1, 1, 0, font, pipe.getFmanholeno());
                writeTitle(table3, 1, 1, 0, font, "");
                writeValue(table3, 1, 1, 0, font, pipe.getFdepth());
                writeTitle(table3, 1, 1, 0, font, "");
                writeValue(table3, 1, 1, 0, font, pipe.getFcoverlevel());
                writeTitle(table3, 1, 1, 0, font, "");
                writeValue(table3, 1, 1, 0, font, pipe.getFinvertlevel());
                tableWrap(table3, 4);
                document.add(table3);

                int[] width4 = new int[]{30, 15, 45, 15, 60, 15, 60, 15, 35, 15, 60, 15, 60, 15, 60, 15, 60, 15, 60, 15, 60};
                PdfPTable table4 = getTable(width4);
                assert table4 != null;
                // 添加title
                writeTitle(table4, 1, 1, 8, font, "Use");
                writeTitle(table4, 1, 1, 0, font, "");
                writeTitle(table4, 1, 1, 0, font, "Direction");
                writeTitle(table4, 1, 1, 0, font, "");
                writeTitle(table4, 1, 1, 0, font, "Size(dia)");
                writeTitle(table4, 1, 1, 0, font, "");
                writeTitle(table4, 1, 1, 0, font, "Size");
                writeTitle(table4, 1, 1, 0, font, "");
                writeTitle(table4, 1, 1, 0, font, "Shape");
                writeTitle(table4, 1, 1, 0, font, "");
                writeTitle(table4, 1, 1, 0, font, "Material");
                writeTitle(table4, 1, 1, 0, font, "");
                writeTitle(table4, 1, 1, 0, font, "Lining");
                writeTitle(table4, 1, 1, 0, font, "");
                writeTitle(table4, 1, 1, 0, font, "Pipe Length");
                writeTitle(table4, 1, 1, 0, font, "");
                writeTitle(table4, 1, 1, 0, font, "Total Length");
                writeTitle(table4, 1, 1, 0, font, "");
                writeTitle(table4, 1, 1, 0, font, "Year Laid");
                writeTitle(table4, 1, 1, 0, font, "");
                writeTitle(table4, 1, 1, 0, font, "Cont. Page No");
                // 添加value
                writeValue(table4, 1, 1, 12, font, pipe.getUses());
                writeTitle(table4, 1, 1, 0, font, "");
                writeValue(table4, 1, 1, 0, font, pipe.getDire());
                writeTitle(table4, 1, 1, 0, font, "");
                writeValue(table4, 1, 1, 0, font, pipe.getHsize());
                writeTitle(table4, 1, 1, 0, font, "  X");
                writeValue(table4, 1, 1, 0, font, pipe.getWsize());
                writeTitle(table4, 1, 1, 0, font, "");
                writeValue(table4, 1, 1, 0, font, pipe.getShape());
                writeTitle(table4, 1, 1, 0, font, "");
                writeValue(table4, 1, 1, 0, font, pipe.getMater());
                writeTitle(table4, 1, 1, 0, font, "");
                writeValue(table4, 1, 1, 0, font, pipe.getLining());
                writeTitle(table4, 1, 1, 0, font, "");
                writeValue(table4, 1, 1, 0, font, pipe.getPipelength() + "");
                writeTitle(table4, 1, 1, 0, font, "");
                writeValue(table4, 1, 1, 0, font, pipe.getTestlength() + "");
                writeTitle(table4, 1, 1, 0, font, "");
                writeValue(table4, 1, 1, 0, font, pipe.getYearlaid());
                writeTitle(table4, 1, 1, 0, font, "");
                writeValue(table4, 1, 1, 0, font, "");
                tableWrap(table4, 4);
                document.add(table4);

                int[] width5 = new int[]{30, 15, 30, 15, 30, 15, 30, 15, 30, 20, 510};
                PdfPTable table5 = getTable(width5);
                assert table5 != null;
                // 添加title
                writeTitle(table5, 1, 3, 8, font, "Video Tape No.");
                writeTitle(table5, 1, 7, 0, font, "");
                writeTitle(table5, 1, 1, 0, font, " Comments General");
                // 添加value
                writeValue(table5, 1, 3, 12, font, pipe.getVideono());
                writeTitle(table5, 1, 7, 0, font, "");
                writeValue(table5, 1, 3, 0, font, pipe.getComment());
                tableWrap(table5, 4);
                // 添加title
                writeTitle(table5, 1, 1, 8, font, "Purpose");
                writeTitle(table5, 1, 1, 0, font, "");
                writeTitle(table5, 1, 1, 0, font, "Cat");
                writeTitle(table5, 1, 1, 0, font, "");
                writeTitle(table5, 1, 1, 0, font, "Preclean");
                writeTitle(table5, 1, 1, 0, font, "");
                writeTitle(table5, 1, 1, 0, font, "Weather");
                writeTitle(table5, 1, 1, 0, font, "");
                writeTitle(table5, 1, 1, 0, font, "Location");
                writeTitle(table5, 1, 1, 0, font, "");
                writeTitle(table5, 1, 1, 0, font, "Further Location Details (Slope Ref.)");
                // 添加value
                writeValue(table5, 1, 1, 12, font, pipe.getPurposes());
                writeTitle(table5, 1, 1, 0, font, "");
                writeValue(table5, 1, 1, 0, font, pipe.getCategory());
                writeTitle(table5, 1, 1, 0, font, "");
                writeValue(table5, 1, 1, 0, font, pipe.getCleaned());
                writeTitle(table5, 1, 1, 0, font, "");
                writeValue(table5, 1, 1, 0, font, pipe.getWeather());
                writeTitle(table5, 1, 1, 0, font, "");
                writeValue(table5, 1, 1, 0, font, "");
                writeTitle(table5, 1, 1, 0, font, "");
                writeValue(table5, 1, 1, 0, font, pipe.getSloperef());
                tableWrap(table5, 6);
                document.add(table5);

                int[] width6 = new int[]{50, 10, 50, 10, 50, 10, 45, 10, 50, 10, 45, 10, 50, 10, 50, 10, 270};
                PdfPTable table6 = getTable(width6);
                assert table6 != null;

                writeValue(table6, 2, 1, 0, font, "Video No.");
                writeTitle(table6, 2, 1, 0, font, "");
                writeValue(table6, 2, 1, 0, font, "Photo No.");
                writeTitle(table6, 2, 1, 0, font, "");
                writeValue(table6, 2, 1, 0, font, "Chainage(m)");
                writeTitle(table6, 2, 1, 0, font, "");
                writeValue(table6, 2, 1, 0, font, "Cont\n" + "defects\n" + "& extra\n" + "line");
                writeValue(table6, 2, 1, 0, font, "");
                writeValue(table6, 1, 1, 10, font, "Letters");
                writeTitle(table6, 1, 1, 0, font, "");
                writeValue(table6, 1, 5, 10, font, "Numbers");
                writeTitle(table6, 1, 1, 0, font, "");
                writeValue(table6, 2, 1, 0, font, "Remarks");
                writeValue(table6, 1, 1, 25, font, "Code");
                writeTitle(table6, 1, 1, 0, font, "");
                writeValue(table6, 1, 1, 25, font, "Dia of\n" + "JN/CN(mm)");
                writeValue(table6, 26, 1, 0, font, color, "");
                writeValue(table6, 1, 1, 25, font, "Clock\n" + "At / To");
                writeValue(table6, 26, 1, 0, font, color, "");
                writeValue(table6, 1, 1, 25, font, "Intrusion\n" + "% / mm");
                writeTitle(table6, 1, 1, 0, font, "");
                for (int i = 0; i < 25; i++) {
                    Item item = i < pipe.getItems().size() ? pipe.getItems().get(i) : null;
                    writeValue(table6, 1, 1, 12, font, item == null ? "" : item.getVideo());
                    writeTitle(table6, 1, 1, 0, font, "");
                    writeValue(table6, 1, 1, 0, font, item == null ? "" : item.getPhoto());
                    writeTitle(table6, 1, 1, 0, font, "");
                    writeValue(table6, 1, 1, 0, font, item == null ? "" : item.getDist());
                    writeTitle(table6, 1, 1, 0, font, "");
                    writeValue(table6, 1, 1, 0, font, item == null ? "" : item.getCont());
                    if (i == 0)
                        writeValue(table6, 25, 1, 0, font, color, "");
                    writeValue(table6, 1, 1, 0, font, item == null ? "" : item.getCode());
                    writeTitle(table6, 1, 1, 0, font, "");
                    writeValue(table6, 1, 1, 0, font, item == null ? "" : item.getDiam());
                    if (item == null)
                        writeValue(table6, 1, 1, 0, font, "");
                    else {
                        if (!StringUtils.isEmpty(item.getClockAt()))
                            writeValue(table6, 1, 1, 0, font, item.getClockAt());
                        else if (!StringUtils.isEmpty(item.getClockTo())) {
                            StringBuffer buffer = new StringBuffer(item.getClockTo());
                            writeValue(table6, 1, 1, 0, font, buffer.insert(2, " / ").toString());
                        } else
                            writeValue(table6, 1, 1, 0, font, "");

                    }
                    if (item == null)
                        writeValue(table6, 1, 1, 0, font, "");
                    else {
                        if (!StringUtils.isEmpty(item.getPercent()))
                            writeValue(table6, 1, 1, 0, font, item.getPercent());
                        else
                            writeValue(table6, 1, 1, 0, font, item.getLengths());
                    }
                    writeTitle(table6, 1, 1, 0, font, "");
                    writeValue(table6, 1, 1, 0, font, item == null ? "" : item.getRemarks());
                }
                document.add(table6);
            }
            // 关闭文档
            document.close();
            return stream;
        } catch (Exception e) {
            return null;
        }
    }

    public void onEndPage(PdfWriter writer, Document document) {
        Font font = getFont(8);
        Phrase phrase = new Phrase("Page: " + writer.getPageNumber(), font);
        ColumnText.showTextAligned(writer.getDirectContent(), 1, phrase, 420, 20, 0);
    }

    private Font getFont(int size) {
        try {
            BaseFont baseFont = BaseFont.createFont("Helvetica", "Cp1252", false);
            return new Font(baseFont, size, 0);
        } catch (DocumentException | IOException e) {
            return null;
        }
    }

    private PdfPTable getTable(int[] widths) {
        try {
            PdfPTable table = new PdfPTable(widths.length);
            table.setLockedWidth(true);
            table.setTotalWidth((float) 740);
            table.setWidths(widths);
            return table;
        } catch (DocumentException e) {
            e.printStackTrace();
            return null;
        }
    }

    private void tableWrap(PdfPTable table, int height) {
        PdfPCell cell = new PdfPCell();
        cell.setColspan(table.getAbsoluteWidths().length);
        cell.setFixedHeight(height);
        cell.setBorderWidth(0);
        table.addCell(cell);
    }

    public void writeTitle(PdfPTable table, int row, int col, int height, Font font, String text) {
        text = text == null ? "" : text;
        Paragraph paragraph = new Paragraph(text, font);
        PdfPCell cell = new PdfPCell(paragraph);
        cell.setHorizontalAlignment(Element.ALIGN_LEFT);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setFixedHeight(height);
        cell.setUseAscender(true);
        cell.setRowspan(row);
        cell.setColspan(col);
        cell.setBorderWidth(0);
        table.addCell(cell);
    }

    public void writeValue(PdfPTable table, int row, int col, int height, Font font, String text) {
        text = text == null ? "" : text;
        Paragraph paragraph = new Paragraph(text, font);
        PdfPCell cell = new PdfPCell(paragraph);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setFixedHeight(height);
        cell.setUseAscender(true);
        cell.setRowspan(row);
        cell.setColspan(col);
        cell.setBorderWidth(1);
        table.addCell(cell);
    }

    public void writeValue(PdfPTable table, int row, int col, int height, Font font, BaseColor color, String text) {
        text = text == null ? "" : text;
        Paragraph paragraph = new Paragraph(text, font);
        PdfPCell cell = new PdfPCell(paragraph);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setBackgroundColor(color);
        cell.setFixedHeight(height);
        cell.setUseAscender(true);
        cell.setRowspan(row);
        cell.setColspan(col);
        cell.setBorderWidth(1);
        table.addCell(cell);
    }

}
